/*
 * =====================================================================================
 *
 *       Filename:  gdc.h
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  12/08/2011 07:02:29 PM
 *       Revision:  none
 *       Compiler:  gcc
 *
 *
 * =====================================================================================
 */

#ifndef __GDC_H__
#define __GDC_H__


#define __X_DEBUG__
#include "libx.h"
#include "basetype.h"

#define GDC_OK  0
#define GDC_ERR -1

#define GDC_MALLOC          xmalloc
#define GDC_FREE            xfree
#define GDC_PRINTF          xprintf
#define GDC_ERROR           xprintf
#define GDC_LIST_ADD_TAIL           xlist_add_tail
#define GDC_LIST_DEL                xlist_del
#define GDC_LIST_EACH_ENTRY         xlist_for_each_entry
#define GDC_LIST_EACH_ENTRY_SAFE    xlist_for_each_entry_safe
#define GDC_ASSERT          assert

#define NGE_MAX_THREAD      2 //8
#define GDC_NODE_8_NUM      8 //64
#define GDC_NODE_32_NUM     8 //64
#define GDC_L2_NODE_8_NUM   8 //1024
#define GDC_L2_NODE_32_NUM  8 //1024
#define GDC_NODE_8_SIZE     8
#define GDC_NODE_32_SIZE    32


typedef enum tagGDCCacheNodeType
{
    GDC_NODE_8 = 0,
    GDC_NODE_32,
} GDCCacheNodeType_EN;

typedef enum tagGDCCacheNodeLevel
{
    GDC_NODE_Level1 = 0,
    GDC_NODE_Level2,
} GDCCacheNodeLevel_EN;

typedef struct tagGDCNode
{
    struct list_head list;          /* 缓存块双向链表 */
    GDCCacheNodeType_EN enType;     /* cache块类型，8字节块或者32字节块 */
    GDCCacheNodeLevel_EN enLevel;   /* 标记为第几级缓存 */
    CHAR *pcMem;                    /* 缓存块指针，指向使用的缓存块地址 */
} GDCNode_ST;

typedef struct tagGDC
{
    struct list_head list;      /* 缓存块链表头 */
    CHAR *pcCache;              /* 缓存第一个数据的指针 */
    UINT32 uiCacheUse;          /* 已使用缓存的长度 */
    UINT32 uiCacheLeft;         /* 剩余缓存可用长度 */
    UINT32 uiMaxLen;            /* 缓存的最大长度 */
    UINT32 uiCacheNum;          /* 缓存块的个数 */
    UINT32 uiIsContinue : 1,    /* 缓存是否是连续内存 */
           uiIsEight    : 1,    /* 缓存是否第一个块是8字节 */
           uiFlag       : 30;
    UINT32 uiFid;               /* 用于记录解码的字段ID信息 */
    UINT32 uiModule;            /* 用于记录使用模块信息 */
    CHAR *pcCacheBuf;           /* 用于取缓存时保存缓存内容：若缓存是连续的则指到缓存头；
                                   若缓存不连续则分配新内存，同时将cache拷贝到这块内存中，
                                   指向新分配内存地址 */
} GDC_ST;

typedef struct tagGDCFreeNode
{
    struct list_head list_node8;        /* 缓存块链表头 */
    struct list_head list_node32;       /* 缓存块链表头 */
    CHAR *pcCache;
    /* TODO: add thread lock */
} GDCFreeNode_ST;


/**
 * GDC_Init - GDC初始化
 *
 * IN  : @uiThreadNum : 线程个数
 * OUT : 
 * RET :
 *       GDC_OK  : 初始化成功
 *       GDC_ERR : 初始化失败
 *
 * 分配GDC用到的所有缓存，一级和二级缓存，初始化缓存链表
 *
 **/
INT32 GDC_Init(UINT32 uiThreadNum);


/**
 * GDC_Cleanup - GDC释放资源
 *
 * IN  :
 * OUT : 
 * RET :
 *       GDC_OK  : 释放成功
 *       GDC_ERR : 释放失败
 *
 * 释放GDC用到的所有缓存，一级和二级缓存
 *
 **/
INT32 GDC_Cleanup(void);


/**
 * GDC_Create - 创建GDC缓存结构体
 *
 * IN  : @uiMaxLen : cache的最大长度
 *       @uiModule    : 使用模块ID
 * OUT : 
 * RET :
 *       GDC_ST* : 创建成功
 *       NULL    : 创建失败
 *
 * 分配GDC结构体内存，初始化结构体各成员变量
 *
 **/
GDC_ST *GDC_Create(UINT32 uiMaxLen, UINT32 uiModule);


/**
 * GDC_Free - 释放GDC缓存结构体
 *
 * IN  : @pstGDC : 待释放的GDC
 * OUT :
 * RET :
 *       GDC_OK  : 释放成功
 *       GDC_ERR : 释放失败
 *
 * 释放GDC结构体内存，归还所有使用的cache块
 *
 **/
INT32 GDC_Free(GDC_ST *pstGDC);


/**
 * GDC_Append - 追加缓存
 *
 * IN  : @pstGDC  : GDC指针
 *       @pcBuf : 待存入cache的数据指针
 *       @uiLen : 待存入cache的数据长度
 * OUT :
 * RET :
 *       INT32  : 实际写入数据长度
 *
 * 当第一次写入cache的长度小于8字节时，第一个cache块为8字节，后续块使用32字节；
 * 否则第一个cache块使用32字节，后续块也使用32字节
 *
 **/
UINT32 GDC_Append(GDC_ST *pstGDC, const CHAR * const pcBuf, UINT32 uiLen);


/**
 * GDC_GetCache - 获取缓存
 *
 * IN  : @pstGDC        : GDC指针
 *       @iCleanCache : 是否清空cache标记，GDC_CLEAN_CACHE或者GDC_KEEP_CACHE
 * OUT :
 * RET :
 *       CHAR*  : cache的数据内容
 *       NULL   : 取cache失败
 *
 * 当所有cache块在连续内存上时直接返回第一块cache的地址，如果cache块地址不连续，
 * 则动态分配一块内存，然后将cache块的内容拷贝到此块内存中。
 * 返回的指针保存在pcCacheBuf指针中。
 *
 **/
#define GDC_CLEAN_CACHE    1   /* 取出并释放cache */
#define GDC_KEEP_CACHE     2   /* 取出cache不释放 */
CHAR *GDC_GetCache(GDC_ST *pstGDC, INT32 iCleanCache);


/**
 * GDC_CombineSMBuf - 缓存和SMBuf合并
 *
 * IN  : @pstGDC   : GDC指针
 *       @pSMBuf : 数据包指针
 * OUT :
 *       @uiLen  : 合并之后数据的长度
 * RET :
 *       CHAR*  : 合并后的数据内容
 *       NULL   : 失败
 *
 * 分配新的内存空间，将缓存cache和SMBuf的数据合并拷贝到这块内存上，同时返回
 * 数据的长度，这块内存的指针保存在pcCacheBuf指针中
 *
 **/
//CHAR *GDC_CombineSMBuf(GDC_ST *pstGDC, SMBUF_S *pSMBuf, UINT32 *uiLen);


/**
 * GDC_FreeCache - 释放缓存
 *
 * IN  : @pstGDC   : GDC指针
 * OUT :
 * RET :
 *       GDC_OK  : 释放成功
 *       GDC_ERR : 释放失败
 *
 * 释放GDC缓存块链，归还所有使用的cache块
 *
 **/
INT32 GDC_FreeCache(GDC_ST *pstGDC);


/**
 * GDC_GetCacheLen - 获取当前缓存长度
 *
 * IN  : @pstGDC   : GDC指针
 * OUT :
 * RET :
 *       UINT32  : 当前cache数据长度
 *
 * 获取当前cache缓存的数据长度
 *
 **/
UINT32 GDC_GetCacheLen(GDC_ST *pstGDC);


/**
 * GDC_GetCacheMaxLen - 获取当前缓存最大长度
 *
 * IN  : @pstGDC   : GDC指针
 * OUT :
 * RET :
 *       UINT32  : 当前cache可保存最大数据长度
 *
 * 获取当前cache可缓存的最大数据长度
 *
 **/
UINT32 GDC_GetCacheMaxLen(GDC_ST *pstGDC);


/**
 * GDC_Dump - 打印GDC调试信息
 *
 * IN  : 
 * OUT :
 * RET :
 *
 **/
void GDC_Dump(void);


#endif /* __GDC_H__ */


